Skip to content

voice: introduce Voice Mode with a first-run card above the chat input - #5

Closed
eli-w-king wants to merge 1 commit into
mainfrom
eli/agents/voice-mode-first-run
Closed

voice: introduce Voice Mode with a first-run card above the chat input#5
eli-w-king wants to merge 1 commit into
mainfrom
eli/agents/voice-mode-first-run

Conversation

@eli-w-king

@eli-w-king eli-w-king commented Jul 28, 2026

Copy link
Copy Markdown
Owner

The gap

Voice Mode can speak back, in one of four model voices — but nothing in the product says so. The setting exists, the voices are only names in a dropdown, and nobody hears one before committing to it. Anyone who would rather not be spoken to is never told dictation is the alternative.

What this adds

A small card above the chat input, the first time a Voice Mode session starts.

It says what Voice Mode is, that it costs nothing, and offers the four voices to audition. Clicking a voice plays it and adopts it in the same gesture — the sample is pre-recorded with that exact model voice, so what you hear is what you get, and there is nothing to confirm afterwards. The leading icon carries that whole story:

state icon
at rest (hover) ▶ play
speaking animating bars
chosen ✓ check

The icon slot is collapsed to width: 0 until hover or selection. Four named buttons plus permanent icons need 261px; the default panel row is 206px, so the slot slides open instead of forcing a wrap.

Details worth calling out

It uses Voice Mode's own instrument. The waveform is the same thin bars and rounded caps as the toolbar equalizer (voiceInputMode.css), just many more of them, so the introduction and the feature it introduces read as one thing. Bars are drawn on canvas rather than as DOM spans — ~50 spans would mean ~50 style writes per frame.

It appears exactly once, gated on an application-scoped storage key. The key is written only once a card is actually shown, so a session started with no chat panel open doesn't silently burn the one appearance.

The trigger watches connection state, not any single entry point. Voice Mode can be started from the input-mode pill, a command, a keybinding or the Agents window; all of them land on isConnecting / isConnected.

Nobody is recorded while reading. While the card is up Voice Mode is connected but not listening. Dismissing hands the session back — hands-free starts listening, push-to-talk waits for the mic.

Hosts. Both the workbench chat input and the Agents window register a container; the most recently focused visible one wins.

Accessibility

role="region" with a label; the voices are a radiogroup of radios with aria-checked and a single tab stop, arrows moving between them. Selection is announced with status(). Escape dismisses. The canvas is aria-hidden, and the animation honours reduced motion.

Validation

  • npm run typecheck-client, npm run valid-layers-check, eslint, stylelint, hygiene — all clean
  • 5 unit tests, including two that were each verified to fail against deliberately broken behaviour
  • Component fixtures at 280px (default panel), 620px (wide) and 240px (narrowest)
  • Smoke-tested in Code OSS end to end: card absent when idle → appears on first connect with all four voices → dismissed → does not return on a second connect

Note

npm run compile currently fails on extensions/markdown-language-features/markdown-editor-src/editor.ts (Property 'revealComment' does not exist). That is pre-existing on main from aac8a5a and untouched by this branch, which changes nothing under extensions/.

Voice Mode can speak back, and it does so in one of four model voices -
but nothing in the product says so. The setting exists, the voices are
only names in a dropdown, and nobody hears one before committing to it.
Anyone who does not want to be spoken to at all is never told that
dictation is the alternative.

Show a small card above the chat input the first time a Voice Mode
session starts. It says what Voice Mode is, that it costs nothing, and
offers the four voices to audition. Clicking a voice plays a short
sample recorded with that exact model voice and adopts it in the same
gesture, so what you hear is what you get and there is nothing to
confirm afterwards. The leading icon carries that story: play before the
click, animating bars while it speaks, a check once it is yours.

The card is deliberately no taller than the input it sits above, and
survives down to a 240px panel. Its waveform is drawn with Voice Mode's
own instrument - the same thin bars and rounded caps as the toolbar
equalizer, just many more of them - so the introduction and the feature
it introduces read as one thing.

It appears exactly once, gated on an application-scoped storage key that
is only written once a card is actually shown, so a session started with
no chat panel open does not silently burn the one appearance. The
trigger watches the voice session's connection state rather than any
single entry point, because Voice Mode can be started from the
input-mode pill, a command, a keybinding or the Agents window.

While the card is up, Voice Mode is connected but not listening: nobody
should be recorded while still reading. Dismissing hands the session
back - hands-free starts listening, push-to-talk waits for the mic.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@eli-w-king

Copy link
Copy Markdown
Owner Author

Superseded by microsoft#327853 — this belongs on the product repo, not the fork.

@eli-w-king eli-w-king closed this Jul 28, 2026
@eli-w-king
eli-w-king deleted the eli/agents/voice-mode-first-run branch July 28, 2026 16:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant